package com.lib.image.widget;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.lib.image.R;

import com.photoview.PhotoViewAttacher;

import timber.log.Timber;

public class RectFrameLayout extends FrameLayout {

    private ImageView mImageView;
    private RectView mRectView;
    private Bitmap bitmap;
    private float degrees;
    private PhotoViewAttacher mPhotoViewAttacher;
    private int mImageLeftPadding;
    private int mImageTopPadding;
    private int mImageRightPadding;
    private int mImageBottomPadding;
    private boolean fixed; //Rect固定
    private int fixedSize; //固定尺寸

    public RectFrameLayout(@NonNull Context context) {
        this(context, null);
    }

    public RectFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RectFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RectFrameLayout);
        int imagePadding = (int) typedArray.getDimension(R.styleable.RectFrameLayout_preview_padding, 0);
        mImageLeftPadding = (int) typedArray.getDimension(R.styleable.RectFrameLayout_preview_left_padding, 0);
        mImageTopPadding = (int) typedArray.getDimension(R.styleable.RectFrameLayout_preview_top_padding, 0);
        mImageRightPadding = (int) typedArray.getDimension(R.styleable.RectFrameLayout_preview_right_padding, 0);
        mImageBottomPadding = (int) typedArray.getDimension(R.styleable.RectFrameLayout_preview_bottom_padding, 0);
        if (imagePadding > 0) {
            mImageLeftPadding = imagePadding;
            mImageTopPadding = imagePadding;
            mImageRightPadding = imagePadding;
            mImageBottomPadding = imagePadding;
        }
        typedArray.recycle();
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        LayoutInflater.from(getContext()).inflate(R.layout.layout_clip_image, this, true);
        mImageView = findViewById(R.id.image_view);
        if(fixed) {
            this.setPadding(mImageLeftPadding, mImageTopPadding, mImageRightPadding, mImageBottomPadding);
        } else {
            mImageView.setPadding(mImageLeftPadding, mImageTopPadding, mImageRightPadding, mImageBottomPadding);
        }
        mRectView = findViewById(R.id.rect_view);
        mRectView.setFixed(fixed);
        mPhotoViewAttacher = new PhotoViewAttacher(mImageView);
        mPhotoViewAttacher.setOnMatrixChangeListener(rect -> {
            RectF displayRect = mPhotoViewAttacher.getDisplayRect();
            displayRect.left += mImageView.getPaddingLeft();
            displayRect.top += mImageView.getPaddingTop();
            displayRect.right += mImageView.getPaddingRight();
            displayRect.bottom += mImageView.getPaddingBottom();
            if (fixed) {
                if (displayRect.height() < fixedSize) {
                    mRectView.setRect(displayRect);
                } else {
                    RectF rectF = new RectF();
                    rectF.left = getLeft() + mImageLeftPadding;
                    rectF.right = getRight() - mImageRightPadding;

                    rectF.top = mImageView.getMeasuredHeight() / 2.0f - fixedSize / 2.0f;
                    rectF.bottom = mImageView.getMeasuredHeight() / 2.0f + fixedSize / 2.0f;
                    mRectView.setRect(rectF);
                }
            } else {
                mRectView.setRect(displayRect);
            }
            mRectView.setMaxRect(displayRect);
        });
    }

    public void setFixed(boolean fixed, int size) {
        this.fixed = fixed;
        this.fixedSize = size;
        if (mRectView != null) {
            mRectView.setFixed(fixed);
        }
    }

    public void setPreviewPadding(int px) {
        mImageLeftPadding = px;
        mImageTopPadding = px;
        mImageRightPadding = px;
        mImageBottomPadding = px;
    }

    public void setPreviewPadding(int left, int top, int right, int bottom) {
        mImageLeftPadding = left;
        mImageTopPadding = top;
        mImageRightPadding = right;
        mImageBottomPadding = bottom;
    }

    private Bitmap rotateBitmap(float degree, Bitmap srcBitmap) {
        Matrix m = mPhotoViewAttacher.getDrawMatrix();
        m.setRotate(degree, (float) srcBitmap.getWidth() / 2, (float) srcBitmap.getHeight() / 2);
        try {
            return Bitmap.createBitmap(srcBitmap, 0, 0, srcBitmap.getWidth(), srcBitmap.getHeight(), m, true);
        } catch (OutOfMemoryError ex) {
        }
        return null;
    }

    public void rotationImage() {
        if (degrees == 0) {
            degrees += 45;
        } else if (degrees >= 360) {
            degrees = 0;
        } else {
            degrees += 45;
        }
        mPhotoViewAttacher.setScale(1);
        mPhotoViewAttacher.setBaseRotation(degrees);
        bitmap = rotateBitmap(degrees, bitmap);
    }

    public void setImageResource(int resourceId) {
        getImageView().setImageResource(resourceId);
    }

    public void setBitmap(Bitmap bitmap) {
        this.bitmap = bitmap;
        getImageView().setImageBitmap(bitmap);
    }

    public Bitmap getBitmap() {
        return mImageView.getDrawingCache(true);
    }

    public ImageView getImageView() {
        return mImageView;
    }

    public Bitmap clip() throws Exception {
        if (bitmap == null && mImageView.getDrawable() != null) {
            bitmap = ((BitmapDrawable) mImageView.getDrawable()).getBitmap();
        }
        if (bitmap == null) throw new Exception("data error, bitmap is null");
        RectF mClipBorderRectF = getClipBorder();
        final Drawable drawable = mImageView.getDrawable();
        final float[] matrixValues = new float[9];
        Matrix displayMatrix = mPhotoViewAttacher.getDrawMatrix();
        displayMatrix.getValues(matrixValues);

        float scale = matrixValues[Matrix.MSCALE_X] * drawable.getIntrinsicWidth() / bitmap.getWidth();
        final float transX = matrixValues[Matrix.MTRANS_X];
        final float transY = matrixValues[Matrix.MTRANS_Y];

        final float cropX = (-transX + mClipBorderRectF.left) / scale;
        final float cropY = (-transY + mClipBorderRectF.top) / scale;
        final float cropWidth = mClipBorderRectF.width() / scale;
        final float cropHeight = mClipBorderRectF.height() / scale;
        return Bitmap.createBitmap(bitmap, (int) cropX, (int) cropY, (int) cropWidth, (int) cropHeight, null, false);
    }

    private RectF getClipBorder() {
        RectF mClipBorderViewRectF = mRectView.getFrameRect();
        mClipBorderViewRectF.top += 12f;
        mClipBorderViewRectF.left += 12f;
        mClipBorderViewRectF.right -= 12f;
        mClipBorderViewRectF.bottom -= 12f;
        RectF displayRect = mPhotoViewAttacher.getDisplayRect();
        if (bitmap.getHeight() >= bitmap.getWidth()) {
            if (mPhotoViewAttacher.getScale() < 1) {
                mClipBorderViewRectF.left = displayRect.left;
                mClipBorderViewRectF.right = displayRect.right;
            }
        } else {
            if (mPhotoViewAttacher.getScale() < 1) {
                mClipBorderViewRectF.top = displayRect.top;
                mClipBorderViewRectF.bottom = displayRect.bottom;
            }
        }
        return mClipBorderViewRectF;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
//        ViewGroup viewGroup = ((ViewGroup)getChildAt(0));
//        if (viewGroup.getChildCount() >= 2) {
//            View view1 = viewGroup.getChildAt(0);
//            View view2 = viewGroup.getChildAt(1);
//            if (view2 instanceof RectView) {
//                RectView rectView = (RectView) view2;
//                if (rectView.isOutTouchArea()) {
//                    view1.onTouchEvent(ev);
//                }
//            }
//        }
        return super.onInterceptTouchEvent(ev);
    }
}
